//
// Created by hrg on 2019/11/23.
//
#include <master.h>
#include <native/task.h>
#include <ecrt/master.h>
#include <cassert>
#include <iostream>
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <time.h>
// #define __TIMEKEEP 

Master::Master(uint32_t index)
    : m_Index_(index)
    , m_Domain_(NULL)
    , m_Master_(NULL)
    , m_DomainPtr_(NULL)
{}

Master::~Master()
{
    if(m_Master_ != NULL)
    {
        ecrt_release_master(m_Master_);
        m_Master_ = NULL;
    }
}

bool Master::Init()
{
    if(m_Master_ != NULL)
    {
        return false;
    }

    m_Master_ = ecrt_request_master(m_Index_);
    if(m_Master_ == NULL)
    {
        return false;
    }

    m_Domain_ = ecrt_master_create_domain(m_Master_);
    if(m_Domain_ == NULL)
    {
        return false;
    }

    if(ecrt_master(m_Master_, &m_MasterInfo_))
    {
        return false;
    }
    return true;
}

bool Master::Config(ec_slave_config_t* slave_conf, int interval){
    assert(m_Master_ != NULL);
    if(ecrt_master_set_send_interval(m_Master_, interval)){
        return false;
    }
    
    if (ecrt_master_select_reference_clock(m_Master_, slave_conf)) {
        return false;
    }
    
    ecrt_master_application_time (m_Master_, rt_timer_read());
    return true;
}

bool Master::CheckLinkStatus(){
    ec_master_link_state_t state;

    ecrt_master_link_state(m_Master_, 0, &state);

    // al_states == 0x8表明没有从站处于初始化状态与预处理状态, 所有的从站都处于OP状态
    if(state.al_states == 0x8){
        return true;
    }
    return false;
}

bool Master::StartMaster(){
    assert(m_Master_ != NULL);

    if(ecrt_master_activate(m_Master_))
    {
        return false;
    }

    m_DomainPtr_ = ecrt_domain_data(m_Domain_);
    if(m_DomainPtr_ == NULL)
    {
        std::cerr << "[ERROR]: ecrt_domain_data return nullptr" << std::endl;
        return false;
    }
    return true;
}

ec_domain_t* Master::GetDomain(){
    return m_Domain_;
}

ec_master_t* Master::GetMaster(){
    return m_Master_;
}

int Master::GetSlvNum(){
    return m_MasterInfo_.slave_count;
}

uint8_t* Master::GetDomainData(){
    return m_DomainPtr_;
}

void Master::RecvFrame(void) {
    assert(m_Master_ != NULL);
#ifdef __TIMEKEEP
    struct timespec start, end;
    long long elapsed;
    // 数据的接收：放到master当中
    if (clock_gettime(CLOCK_MONOTONIC, &start) == -1) {
        perror("clock gettime");
        return ;
    }
#endif

    ecrt_master_receive(m_Master_);
#ifdef __TIMEKEEP
    if (clock_gettime(CLOCK_MONOTONIC, &end) == -1) {
        perror("clock gettime");
        return ;
    }
    elapsed = (end.tv_sec - start.tv_sec) * 1000000000LL + end.tv_nsec - start.tv_nsec;
    printf("rx: %7lld ns\n", elapsed);
#endif
    ecrt_domain_process(m_Domain_);
}

bool Master::CheckSlaveState(){
    // ecrt_domain_state
    ecrt_master_state(m_Master_, &currstate_);
    if(currstate_.slaves_responding != m_MasterInfo_.slave_count)
        return false;
    return true;
}

void Master::SendFrame(void) {
    assert(m_Master_ != NULL);
#ifdef __TIMEKEEP
    struct timespec start, end;
    long long elapsed;
#endif
    ecrt_domain_queue(m_Domain_);

    // 同步dc时钟
    ecrt_master_application_time (m_Master_, rt_timer_read());
    ecrt_master_sync_reference_clock(m_Master_);
    ecrt_master_sync_slave_clocks (m_Master_);
#ifdef __TIMEKEEP
    if (clock_gettime(CLOCK_MONOTONIC, &start) == -1) {
        perror("clock gettime");
        return ;
    }
#endif
    // 发送ethercat帧
    ecrt_master_send(m_Master_);
#ifdef __TIMEKEEP
    if (clock_gettime(CLOCK_MONOTONIC, &end) == -1) {
        perror("clock gettime");
        return ;
    }
    elapsed = (end.tv_sec - start.tv_sec) * 1000000000LL + end.tv_nsec - start.tv_nsec;
    printf("rx: %7lld ns\n", elapsed);
#endif
}
